#ifndef __SOCKET_H__
#define __SOCKET_H__

#define MAXMSG 100

/*  http://www.adp-gmbh.ch/win/misc/Sockets.html
 *  http://www.geocities.com/siliconvalley/2072/sockprog.htm
 *  http://trac.matthewwilkes.eu/browser/bee/trunk/BeeGame/src/podinterface.cpp
 *  http://sage.mc.yu.edu/kbeen/teaching/networking/resources/Sockets.html - unix cpp Sockets tutorial
 */

#ifdef WIN32
    #include <winsock.h>
    //#include <winsock2.h>
#else
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <fcntl.h>
    #include <stdio.h>
#endif

#ifdef WIN32
    typedef int socklen_t;
#else
    typedef int SOCKET;
#endif

#include <errno.h>
#include <cassert>
#include <iostream>
#include <string>
#include <vector>

typedef enum {tcp, udp} socketType;

/*
 *  Socket class to provide base functionlaity
 */
class Socket
{
    public:
        Socket(void);
        virtual ~Socket();          // destructor 
        Socket(const Socket&);      // copy constructor
        Socket& operator=(Socket&); // overload assignment operator
        bool operator ==(Socket&);
        bool operator !=(Socket&);
        void disconnect();
        
        int sendUnsignedInt(Socket *, unsigned int);
        int sendStruct(Socket*, void*, size_t);
        int sendStructTo(Socket *, sockaddr_in*, void* data, size_t n);
        int sendString(Socket *, char *);
        int receiveUnsignedInt(Socket*, unsigned int*);
        int receiveStruct(Socket*, void*, size_t);
        int receiveStructFrom(Socket *, sockaddr_in*, void* data, size_t n);
        char* receiveString(Socket *, char *);
        virtual void receiveError(int, Socket *);

    protected:
        friend class SocketServer;
        friend class SocketClient;
        friend class PodServer;
        Socket(int, socketType);
        Socket(int id, socketType, SOCKET);
        socketType type;
        SOCKET s;                  // Socket file descriptor
        int id;
        int *refCounter;           // keep track of references to this object

    private:
        static void start();
        static int noSockets;      // keep track of no Sockets

};

#endif
